package StudyCode.summary.myfile;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.EnumSet;

import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
 * 版权所有 科技与人文(www.tah1986.com)
 */
public class CopyFileWithFileVisitor {
	public static void main(String[] args) throws IOException {
		Path copyFrom = Paths.get("E:/迅雷下载");
		Path copyTo = Paths.get("E:/Copy");
		CopyTree walk = new CopyTree(copyFrom, copyTo);
		EnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
		Files.walkFileTree(copyFrom, opts, Integer.MAX_VALUE, walk);
	}
}

class CopyTree implements FileVisitor<Object> {
	Path copyFrom;
	Path copyTo;

	public CopyTree(Path copyFrom, Path copyTo) {
		this.copyFrom = copyFrom;
		this.copyTo = copyTo;
	}

	static void copySubTree(Path copyFrom, Path copyTo) {
		try {
			Files.copy(copyFrom, copyTo, REPLACE_EXISTING, COPY_ATTRIBUTES);
		} catch (IOException e) {
			System.err.println("不能复制 " + copyFrom + " [" + e + "]");
		}
	}

	@Override
	public FileVisitResult postVisitDirectory(Object dir, IOException exc)
			throws IOException {
		if (exc == null) {
			Path newdir = copyTo.resolve(copyFrom.relativize((Path) dir));
			try {
				FileTime time = Files.getLastModifiedTime((Path) dir);
				Files.setLastModifiedTime(newdir, time);
			} catch (IOException e) {
				System.err.println("不能复制所有属性到: " + newdir + " [" + e + "]");
			}
		} else {
			throw exc;
		}

		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs) {
		System.out.println("复制目录: " + dir);
		Path newdir = copyTo.resolve(copyFrom.relativize((Path) dir));
		try {
			Files.copy((Path) dir, newdir, REPLACE_EXISTING, COPY_ATTRIBUTES);
		} catch (IOException e) {
			System.err.println("不能创建 " + newdir + " [" + e + "]");
			return FileVisitResult.SKIP_SUBTREE;
		}

		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult visitFile(Object file, BasicFileAttributes attrs) {
		System.out.println("复制文件 : " + file);
		copySubTree((Path) file, copyTo.resolve(copyFrom.relativize((Path) file)));
		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult visitFileFailed(Object file, IOException exc) {
		if (exc instanceof FileSystemLoopException) {
			System.err.println("检测到循环: " + file);
		} else {
			System.err.println("发生错误，无法复制:" + file + " [" + exc + "]");
		}
		return FileVisitResult.CONTINUE;
	}
}
